package
{
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 *@date 2017-1-6 上午11:29:34
	 *@author zhouhonghui
	 */
	public class Scale9GridData
	{
		/**源 位图数据**/
		private var _srcBmpData:BitmapData;
		
		/**左上角**/
		private var _tlBmd:BitmapData;
		/**顶部中间**/
		private var _tmBmd:BitmapData;
		/**右上角**/
		private var _trBmd:BitmapData;
		/**左边中间**/
		private var _lmBmd:BitmapData;
		/**中间**/
		private var _mmBmd:BitmapData;
		/**右边中间**/
		private var _rmBmd:BitmapData;
		/**左下角**/
		private var _blBmd:BitmapData;
		/**底部中间**/
		private var _bmBmd:BitmapData;
		/**右下角**/
		private var _brBmd:BitmapData;

		private var _leftSpace:Number;

		private var _topSpace:Number;

		private var _rightSpace:Number;

		private var _bottomSpace:Number;
		
		private var _bmpSrcs:Array;
		
		public function Scale9GridData(src:BitmapData,left:Number,top:Number,right:Number,bottom:Number)
		{
			this._bottomSpace = bottom;
			this._rightSpace = right;
			this._topSpace = top;
			this._leftSpace = left;
			_srcBmpData = src;		
			_bmpSrcs = [];
			check();
			splitBmp(_srcBmpData);
		}
		
		private function check():void
		{
			var bw:Number = _srcBmpData.width;
			var bh:Number = _srcBmpData.height;
			if((_leftSpace+_rightSpace)>bw || (_topSpace+_bottomSpace)>bh)
			{
				throw new Error("对宽高为"+bw+","+bh+"的位图设置了无效的左上右下为:"+_leftSpace+
				','+_topSpace+','+_rightSpace+','+_bottomSpace+'的九宫格参数');
			}
			if(_leftSpace<=0 || _rightSpace<=0 || _topSpace<=0 || _bottomSpace<=0)
			{
				throw new Error("九宫格格参数不能包括0,左上右下为"+_leftSpace+
					','+_topSpace+','+_rightSpace+','+_bottomSpace);
			}
		}
		/**
		 * 把源图片切割成九个图片 
		 * @param src
		 * 
		 */		
		private function splitBmp(src:BitmapData):void
		{
			// --- 下列切割顺序不要改变 否则会导致 bmpSrcs里面的数据不对应了
			var bw:Number = src.width;
			var bh:Number = src.height;
			
			var midW:Number = bw-_leftSpace-_rightSpace;
			var midH:Number = bh-_topSpace-_bottomSpace;
			
			var rect:Rectangle = new Rectangle();
			
			rect.x = 0;
			rect.y = 0;
			rect.width = _leftSpace;
			rect.height = _topSpace;
			_tlBmd = copyBmpd(src,rect);
			
			rect.x = _leftSpace;
			rect.y = 0;
			rect.width = midW;
			rect.height = _topSpace;
			_tmBmd = copyBmpd(src,rect);
			
			rect.x = bw-_rightSpace;
			rect.y = 0;
			rect.width = _rightSpace;
			rect.height = _topSpace;
			_trBmd = copyBmpd(src,rect);
			
			rect.x = 0;
			rect.y = _topSpace;
			rect.width = _leftSpace;
			rect.height = midH;
			_lmBmd = copyBmpd(src,rect);
			
			rect.x = _leftSpace;
			rect.y = _topSpace;
			rect.width = midW;
			rect.height = midH;
			_mmBmd = copyBmpd(src,rect);
			
			rect.x = bw-_rightSpace;
			rect.y = _topSpace;
			rect.width = _rightSpace
			rect.height = midH;
			_rmBmd = copyBmpd(src,rect); 
			
			rect.x = 0;
			rect.y = bh-_bottomSpace;
			rect.width = _leftSpace;
			rect.height = _bottomSpace;
			_blBmd = copyBmpd(src,rect); 
			
			rect.x = bw-_leftSpace;
			rect.y = bh-_bottomSpace;
			rect.width = midW;
			rect.height = _bottomSpace;
			_bmBmd = copyBmpd(src,rect); 
			
			rect.x = bw-_rightSpace;
			rect.y = bh-_bottomSpace;
			rect.width = _rightSpace;
			rect.height = _bottomSpace;
			_brBmd = copyBmpd(src,rect);
			
		}
		
		private function copyBmpd(src:BitmapData,rect:Rectangle):BitmapData
		{
			var newBmpd:BitmapData = new BitmapData(rect.width,rect.height);
			newBmpd.copyPixels(src,rect,new Point());
			_bmpSrcs.push(newBmpd);
			return newBmpd;
		}
		/**
		 * 返回一个指定尺寸的位图 
		 * @param w
		 * @param h
		 * @return 
		 * 
		 */		
		public function makeBitmapData(sizeW:Number,sizeH:Number):BitmapData
		{
			/*
			在设置 scale9Grid 属性并缩放显示对象后，会正常缩放所有文本和渐变；但是，对于对象的其它类型，将应用以下规则：			
				1.正常缩放中心区域中的内容。 
				2.不缩放转角中的内容。 
				3.仅水平缩放顶部和底部区域中的内容。 仅垂直缩放左侧和右侧区域中的内容。
				4.拉伸所有填充（包括位图、视频和渐变）以适应其形状。
			*/
			var resultBmd:BitmapData = new BitmapData(sizeW,sizeH,true,0x88ff0000);
			var srcW:Number = _srcBmpData.width; //源图片宽
			var srcH:Number = _srcBmpData.height; //原图片高
			var rect:Rectangle = new Rectangle();
			var dest:Point = new Point();
			var mt:Matrix = new Matrix();
			rect.width = _tlBmd.width;
			rect.height = _tlBmd.height;
			
			var srcMidW:Number = srcW-_leftSpace-_rightSpace;
			var srcMidH:Number = srcH-_topSpace-_bottomSpace;
			//水平方向的缩放
			var hScale:Number = (sizeW-_leftSpace-_rightSpace)/srcMidW;
			//垂直方向的缩放
			var vScale:Number = (sizeH-_topSpace-_bottomSpace)/srcMidH;
			
			//----------- 开始  --------------
			resultBmd.copyPixels(_tlBmd,rect,dest); //左上角保持原始的(参看第2条规则)
			
			mt.tx = _leftSpace;
			mt.ty = 0;
			mt.a = hScale;
			resultBmd.draw(_tmBmd,mt); //顶部中间 水平缩放
			
			rect.width = _trBmd.width;
			rect.height = _trBmd.height;
			dest.x = sizeW-_rightSpace;
			dest.y = 0;
			resultBmd.copyPixels(_trBmd,rect,dest); //右上角保持原来的
			
			mt.tx = 0;
			mt.ty = _topSpace;
			mt.a = 1;
			mt.d = vScale;
			resultBmd.draw(_lmBmd,mt); //垂直缩放左边中间
			
			mt.tx = _leftSpace;
			mt.ty = _topSpace;
			mt.a = hScale;
			mt.d = vScale;			
			resultBmd.draw(_mmBmd,mt); //水平垂直缩放中间的
			
			mt.tx = sizeW-_rightSpace;
			mt.ty = _topSpace;
			mt.d = vScale;
			resultBmd.draw(_rmBmd,mt);//垂直缩放右边中间
			
			rect.width = _blBmd.width;
			rect.height = _blBmd.height;	
			dest.x = 0;
			dest.y = sizeH-_bottomSpace;
			resultBmd.copyPixels(_blBmd,rect,dest); //左下角保持不变
			
			mt.tx = _leftSpace;
			mt.ty = sizeH-topSpace;
			mt.d = 1;
			mt.a = hScale;
			resultBmd.draw(_bmBmd,mt); //水平缩放底部中间块
			
			rect.width = _brBmd.width;
			rect.height = _brBmd.height;	
			dest.x = sizeW-_rightSpace;
			dest.y = sizeH-_bottomSpace;
			resultBmd.copyPixels(_brBmd,rect,dest); //右下角保持不变
			
			return resultBmd;
		}
		/**
		 * 重置九宫格源数据 
		 * @param src   源图片
		 * @param left
		 * @param top
		 * @param right
		 * @param bottom
		 * 
		 */		
		public function setBitmapData(src:BitmapData,left:Number,top:Number,right:Number,bottom:Number):void
		{
			if(_srcBmpData)
			{
				_srcBmpData.dispose();
			}
			this._bottomSpace = bottom;
			this._rightSpace = right;
			this._topSpace = top;
			this._leftSpace = left;
			_srcBmpData = src;		
			check();
			splitBmp(_srcBmpData);
		}
		
		/**
		 * 切割出来的九个图片 <br>
		 * 可以按照行逐个获取到对应的 <br>
		 * 数组前三个元素是九宫格第一行的三个图片源 依此类推 <br>
		 * 0 1 2 <br>
		 * 3 4 5 <br>
		 * 7 8 9 
		 */		
		public function get bmpSrcs():Array
		{
			return _bmpSrcs;
		}

		public function get leftSpace():Number
		{
			return _leftSpace;
		}

		public function set leftSpace(value:Number):void
		{
			_leftSpace = value;
		}

		public function get topSpace():Number
		{
			return _topSpace;
		}

		public function set topSpace(value:Number):void
		{
			_topSpace = value;
		}

		public function get rightSpace():Number
		{
			return _rightSpace;
		}

		public function set rightSpace(value:Number):void
		{
			_rightSpace = value;
		}

		public function get bottomSpace():Number
		{
			return _bottomSpace;
		}

		public function set bottomSpace(value:Number):void
		{
			_bottomSpace = value;
		}
		
	}
}